package com.xmh.utils.reptile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.alibaba.fastjson.JSONObject;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.xmh.test.dao.SexVideoDAO;
import com.xmh.test.other.HtmlUtil;
import com.xmh.test.vo.SexVideoEntity;
import com.xmh.utils.FileUtil;
import com.xmh.utils.RedisClient;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring_bean.xml")
//@Transactional
public class SexReptile {

	private final Logger logger = Logger.getLogger(this.getClass());

	private final long timeoutMillis = 3000L;
	// https://se.dog/
	// xxxrr8.com 7qqqcc.com zzvvv2.com
	private final String DOMAIN_NAME = "https://3yyyuu.com/";

	
	private final String monthHomeUrl = DOMAIN_NAME + "video/monthly-ranking?page=";
	private final String monthDetailPageUrl = DOMAIN_NAME + "video/detail/";

	private final String monthHomeUrl2 = DOMAIN_NAME + "smallvideo/monthly-ranking?page=";
	private final String monthDetailPageUrl2 = DOMAIN_NAME + "smallvideo/detail/";

	@Autowired
	private SexVideoDAO dao;

	@Autowired
	private ThreadPoolTaskExecutor poolTaskExecutor;

	private final ExecutorService executorService = Executors.newCachedThreadPool();

	final WebClient webClient = new WebClient(BrowserVersion.CHROME);// 新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

	@Test
	public void main() throws IOException, InterruptedException {
		saveDownloadId(monthHomeUrl, monthDetailPageUrl);
//		startDownload();
	}

	private void startDownload() throws InterruptedException {
		List<SexVideoEntity> selectDownloadList = dao.selectDownloadList();
		for (SexVideoEntity sexVideoEntity : selectDownloadList) {
			poolTaskExecutor.execute(() -> {
				String oldTitle = sexVideoEntity.getTitle();
				Future<String> future = executorService.submit(() -> {
					downloadZip(sexVideoEntity);
					return "sueecs";
				});
				try {
					// 设置超时时间
					future.get(60L * 60L * 10L, TimeUnit.SECONDS);
				} catch (Exception e) {
					future.cancel(true);
					logger.error("");
					logger.error("====================== 下载超时 ==========================");
					logger.error("标题：" + oldTitle);
					logger.error(e);
					logger.error("");
					new File("I:\\download\\" + oldTitle.replace("/", "_").replace(" ", "_")).delete();
				}
			});
			Thread.sleep(timeoutMillis);
		}
		Thread.sleep(1000L * 60L * 60L * 24L * 3L);
	}

	private void saveDownloadId(String homeUrl, String detailUrl) throws IOException, MalformedURLException {
		webClient.getOptions().setThrowExceptionOnScriptError(false);// 当JS执行出错的时候是否抛出异常, 这里选择不需要
		webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);// 当HTTP的状态非200时是否抛出异常, 这里选择不需要
		webClient.getOptions().setActiveXNative(false);
		webClient.getOptions().setCssEnabled(false);// 是否启用CSS, 因为不需要展现页面, 所以不需要启用
		webClient.getOptions().setJavaScriptEnabled(true); // 很重要，启用JS
		webClient.setJavaScriptEngine(new MyJavaScriptEngine(webClient));// 自定义JavaScript引擎，有js错误不打印
		webClient.setAjaxController(new NicelyResynchronizingAjaxController());// 很重要，设置支持AJAX

		try {
			webClient.getPage(DOMAIN_NAME + "video/detail/230613?ccc=3yyyuu.com");
		} catch (Exception e) {
			e.printStackTrace();
		}

		webClient.waitForBackgroundJavaScript(3000);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

		String path = "d:/SexVideo.txt";

		String fileStr = FileUtil.getFileStr(path);

		int index = 620;

		if (StringUtils.isNotEmpty(fileStr)) {
			index = Integer.parseInt(fileStr);
		}

		for (int i = index; i <= 88617; i++) {
			FileUtil.outFile(i + "", path);

			Document document = null;

			try {
				document = Jsoup.connect(homeUrl + i).get();
			} catch (Exception e) {
				logger.error("------------------请求翻页报错-----------------" + i);
				logger.error(e);
				continue;
			}

			Iterator<Element> iterator = document.select("div[class='pure-u-1 thumbnail'] > a[target='_blank']")
					.iterator();
			while (iterator.hasNext()) {
				Element next = iterator.next();

				String substr = StringUtils.substringBetween(next.attr("href"), "detail/", "#");

				String urlString = detailUrl + substr + "#header";

				HtmlPage page = null;
				try {
					page = webClient.getPage(urlString);
				} catch (Exception e) {
					logger.error("-----------------打开详情页错误----------------");
					logger.error(e);
					continue;
				}

				webClient.waitForBackgroundJavaScript(timeoutMillis);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

				String pageXml = page.asXml();

				if (pageXml.contains("购买本站VIP卡密以后,填写VIP卡号和VIP卡密,点击\"充值VIP\"即可成为VIP")) {
					HtmlForm form = page.getForms().get(0);
					HtmlTextInput txtUName = (HtmlTextInput) form.getInputByName("c1"); //
					txtUName.setValueAttribute("0118659813");

					HtmlTextInput txtPwd = (HtmlTextInput) form.getInputByName("c2");// 密码框
					txtPwd.setValueAttribute("1908282238");

					form.getButtonByName("").click();

					webClient.waitForBackgroundJavaScript(timeoutMillis);// 等待1秒

					page = webClient.getPage(urlString);

					webClient.waitForBackgroundJavaScript(timeoutMillis);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

					pageXml = page.asXml();
				}
				Document parse = Jsoup.parse(pageXml);

				String downId = getDownloadId(pageXml);

				String lodTiele = parse.getElementById("title").text();

				if (downId.equals("0")) {
					continue;
				}
				Integer valueOf = Integer.valueOf(downId);

				SexVideoEntity sexVideo = new SexVideoEntity();
				sexVideo.setDownid(valueOf);

				SexVideoEntity sexVideoEntity = dao.get(sexVideo);
				if (sexVideoEntity != null) {
					if (!sexVideoEntity.getState()) {
						sexVideoEntity.setPath("null");
					}
					sexVideoEntity.setCover("https://sssjj3.com" + next.selectFirst("img").attr("src"));
					dao.update(sexVideoEntity);
					continue;
				}

				SexVideoEntity entity = new SexVideoEntity();
				entity.setTitle(lodTiele);
				entity.setDownid(valueOf);
				entity.setCover("https://sssjj3.com" + next.selectFirst("img").attr("src"));
				entity.setUrl(DOMAIN_NAME + "cdn/xx/file/" + downId + "/");
				entity.setState(false);
				dao.add(entity);
			}
		}
	}

	private String getDownloadId(String pageXml) {
		String substringBetween2 = StringUtils.substringBetween(pageXml,
				"<video class=\"pure-u-1\" src=\"/cdn/xx/file/", "/\" poster");

		if (NumberUtils.isNumber(substringBetween2)) {
			return substringBetween2;
		}

		String substringBetween = StringUtils.substringBetween(pageXml, "hls.loadSource(\"/cdn/hls/", ".");

		if (NumberUtils.isNumber(substringBetween)) {
			return substringBetween;
		}

		return null;
	}

	private void downloadZip(SexVideoEntity sexVideoEntity) {
		String title = sexVideoEntity.getTitle().replace("/", "_").replace(" ", "_");

//		String downloadUrl = getDownloadUrl(lodTiele, downId);
		String downloadUrl = DOMAIN_NAME + "cdn/xx/file/" + sexVideoEntity.getDownid() + "/";

		String pathname = "I:\\download\\" + title;

		System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3");
		logger.info("");
		logger.info("====================== 下载开始==========================");
		logger.info("标题：" + title);
		logger.info("地址：" + downloadUrl);
		logger.info("");
		File file = new File(pathname);
		FileOutputStream fileOutputStream = null;
		InputStream inputStream = null;
		try {
			fileOutputStream = new FileOutputStream(file);

			URL url = new URL(downloadUrl);

			URLConnection connection = url.openConnection();

			inputStream = connection.getInputStream();

			int length = 0;
			byte[] bytes = new byte[1024];
			while ((length = inputStream.read(bytes)) != -1) {
				fileOutputStream.write(bytes, 0, length);
			}
			fileOutputStream.close();
			inputStream.close();

			sexVideoEntity.setState(true);
			sexVideoEntity.setPath(pathname);
			dao.update(sexVideoEntity);
			logger.info("");
			logger.info("======================下载完成==========================");
			logger.info("标题：" + title);
			logger.info("");
		} catch (Exception e) {
			logger.error("======================下载报错==========================");
			logger.error("标题：" + title);
			logger.error("地址：" + downloadUrl);
			logger.error(e);
			try {
				if (fileOutputStream != null) {
					fileOutputStream.close();
				}
				if (inputStream != null) {
					inputStream.close();
				}
			} catch (IOException e1) {
				logger.error(e1);
			}
			file.delete();
		}
	}

	public String getDownloadUrl(String title, String downId) {
		try {
			String titleEncode = URLEncoder.encode(title, "utf8").replace("+", "%20");

			int x = 15;
			int y = 6;

			return "https://x" + x + "y" + y + ".qq360cn.com/xx/file/" + downId + "/" + titleEncode;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	public int getRandom(int min, int max) {
		Random ra = new Random();
		int x = ra.nextInt(max + 1 - min) + min;
		return x;
	}

	private void page(String url) {
		final WebClient webClient = new WebClient(BrowserVersion.CHROME);// 新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

		webClient.getOptions().setThrowExceptionOnScriptError(false);// 当JS执行出错的时候是否抛出异常, 这里选择不需要
		webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);// 当HTTP的状态非200时是否抛出异常, 这里选择不需要
		webClient.getOptions().setActiveXNative(false);
		webClient.getOptions().setCssEnabled(false);// 是否启用CSS, 因为不需要展现页面, 所以不需要启用
		webClient.getOptions().setJavaScriptEnabled(true); // 很重要，启用JS
		webClient.setAjaxController(new NicelyResynchronizingAjaxController());// 很重要，设置支持AJAX

		HtmlPage page = null;
		try {
			page = webClient.getPage("http://ent.sina.com.cn/film/");// 尝试加载上面图片例子给出的网页
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			webClient.close();
		}

		webClient.waitForBackgroundJavaScript(30000);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

		String pageXml = page.asXml();// 直接将加载完成的页面转换成xml格式的字符串

		// TODO 下面的代码就是对字符串的操作了,常规的爬虫操作,用到了比较好用的Jsoup库

		Document document = Jsoup.parse(pageXml);// 获取html文档
		List<Element> infoListEle = document.getElementById("feedCardContent").getElementsByAttributeValue("class",
				"feed-card-item");// 获取元素节点等
		infoListEle.forEach(element -> {
			System.out.println(element.getElementsByTag("h2").first().getElementsByTag("a").text());
			System.out.println(element.getElementsByTag("h2").first().getElementsByTag("a").attr("href"));
		});
	}

	@Test
	public void test2() throws IOException, InterruptedException {
		poolTaskExecutor.execute(() -> {
			System.out.println("1");
			String url = "http://localhost:8080/userPayController/selectList?amnout=9";

			String doGet = HtmlUtil.doGet(url);

			System.out.println("2");
			System.out.println(doGet);
		});

//		ExecutorService executor = Executors.newSingleThreadExecutor();
//		Callable<Result> work = new Callable<Result>() {
//		    @Override
//		    public Result call() {
//		        // do something
//		        return  result
//		    }
//		};
//		Future<Result> future = executor.submit(work);
//		try {
//		    result = future.get(TIMEOUT, TIMEUNIT); 
//		} catch (TimeoutException e) { 
//		    ...
//		} catch (...) {
//		    ...
//		}

		Thread.sleep(10000);
	}

	@Test
	public void test3() throws InterruptedException {
		try {
			runWithTimeout(() -> {
				while (true)
					System.out.println("运行中············");
			}, 1, TimeUnit.SECONDS);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("结束1");
		Thread.sleep(2000L);
		System.out.println("结束2");
	}

	public void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
		runWithTimeout(() -> {
			runnable.run();
			return null;
		}, timeout, timeUnit);
	}

	public <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
//		final ExecutorService executor = Executors.newSingleThreadExecutor();
//		final Future<T> future = executor.submit(callable);
		Future<T> future = poolTaskExecutor.submit(callable);
		try {
			return future.get(timeout, timeUnit);
		} catch (Exception e) {
			future.cancel(true);
			throw e;
		}
	}

	@Test
	public void test4() {
		HashMap<String, Object> jsonMap = new HashMap<String, Object>();
		jsonMap.put("state", true);
		List<SexVideoEntity> selectList = dao.selectList(jsonMap);
		for (SexVideoEntity sexVideoEntity : selectList) {
			File file = new File(sexVideoEntity.getPath());
			if (file.exists()) {
				File newName = new File("I:\\共享文件夹\\SexVideo\\" + sexVideoEntity.getTitle());
				file.renameTo(newName);
			}
		}
	}

	@Test
	public void test5() throws UnsupportedEncodingException {
		HashMap<String, Object> jsonMap = new HashMap<String, Object>();

		jsonMap.put("state", true);

		List<SexVideoEntity> selectList = dao.selectList(jsonMap);

		String jsonString = JSONObject.toJSONString(selectList);

		FileUtil.outFile(jsonString, "d:/json.js");

//		String encode = System.out.println(encode);
	}

}
